package com.realtyManage.springboot.Controller;

import com.alibaba.fastjson.JSON;
import com.realtyManage.springboot.Config.AliMessage;
import com.realtyManage.springboot.Model.Do.*;
import com.realtyManage.springboot.Model.Security;
import com.realtyManage.springboot.Model.Vo.*;
import com.realtyManage.springboot.Service.*;
import com.realtyManage.springboot.Utils.CoreUtils;
import com.realtyManage.springboot.Utils.HttpClientUtil;
import com.realtyManage.springboot.Utils.SpringContextUtil;
import com.realtyManage.springboot.Utils.SysExecRsUtil;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.realtyManage.springboot.Utils.CoreUtils.ajaxReturn;

/**
 * PublicController
 *
 * @Author 杭州素色网络科技有限公司
 * @Date 2019/7/22
 * 公共控制器
 **/

@Controller
@ResponseBody
@RequestMapping("/")
public class PublicController {

    @Autowired
    protected BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private IUserService userService;

    @Autowired
    private IAgreementService agreementService;

    @Autowired
    private IApplyInfoService applyInfoService;

    @Autowired
    private ICityService cityService;

    @Autowired
    private ISmsService smsService;

    @Autowired
    private IHouseDetailService houseDetailService;

    @Autowired
    private IShopService shopService;

    /**
     * 发送短信验证码
     *
     * @return
     */
    @RequestMapping(value = "get_code",method = RequestMethod.POST)
    private String getCode(HttpServletResponse response, HttpServletRequest request) {
        //Integer sysCode = (Integer) request.getSession().getAttribute("sysCode");
        Integer sysCode = 1;
        // 用于判断验证是用来注册或是其他用途 1:注册 2:更换密码 3:通过手机号更换密码
        int type = Integer.parseInt(request.getParameter("type"));
        RegEntity regInfo = new RegEntity();
        // 可能已经发送，用户再次点击发送验证码
        if (sysCode == null) {
            int sysCodeNew = (int) ((Math.random() * 9 + 1) * 1000);
            request.getSession().setAttribute("sysCode", sysCodeNew);
            regInfo.setValidateCode(String.valueOf(sysCodeNew));
            regInfo.setInfoCode(-103);
            regInfo.setInfoText(SysExecRsUtil.getMsgFromCode(-103));
            return JSON.toJSONString(regInfo);
            //return ajaxReturn(response, sysCodeNew, "请输入正确的验证码", -3);
        }

        // 检测系统验证码是否正确 发送后将session中的值删除
        String keycodeS = request.getParameter("keycode");
        if(keycodeS.equals("")) {
            regInfo.setInfoCode(-102);
            regInfo.setInfoText(SysExecRsUtil.getMsgFromCode(-102));
            return JSON.toJSONString(regInfo);
        }
        int keycode = Integer.parseInt(keycodeS);
        if (sysCode != keycode) {
            regInfo.setInfoCode(-103);
            regInfo.setInfoText(SysExecRsUtil.getMsgFromCode(-103));
            return JSON.toJSONString(regInfo);
        }

        String phone = request.getParameter("phone");
        if (type == 1) {//注册验证
            // 检测是否已经被注册
            /*if (userService.isExistPhone(phone)) {
                // 存在
                regInfo.setInfoCode(-101);
                regInfo.setInfoText(SysExecRsUtil.getMsgFromCode(-101));
                return JSON.toJSONString(regInfo);
            }*/
        }
        if (type == 3) {//登录验证
            // 检测是否已经被注册
            if (!userService.isExistPhone(phone)) {
                // 存在
                regInfo.setInfoCode(-104);
                regInfo.setInfoText(SysExecRsUtil.getMsgFromCode(-104));
                return JSON.toJSONString(regInfo);
            }
        }

        // 注册时用的验证
        String checkCode = CoreUtils.getCodeSn(6);// 生6位成验证码
        System.out.println("checkCode：" + checkCode);
        /*request.getSession().setAttribute("checkCode", checkCode);// 将验证码放入session
        request.getSession().setAttribute("currentTime", CoreUtils.getTime());// 将当前时间放入session
        request.getSession().setAttribute("phone", phone);*/
        Sms sms = new Sms();
        sms.setPhone(phone.toString());
        sms.setChkCode(checkCode);
        //sms.setCurTime(CoreUtils.getTime());
        sms.setCurTime(System.currentTimeMillis());
        if(smsService.findByPhone(phone.toString())!=null){
            smsService.delSms(phone.toString());
        }
        smsService.insert(sms);

        String result = AliMessage.sendMessage(phone, checkCode);
        if (result != null && result.equals("OK")) {
            request.getSession().removeAttribute("sysCode");
            regInfo.setInfoCode(1);
            regInfo.setInfoText(SysExecRsUtil.getMsgFromCode(1));
            return JSON.toJSONString(regInfo);
        } else {
            request.getSession().removeAttribute("sysCode");
            request.getSession().setAttribute("checkCode", null);
            regInfo.setInfoCode(0);
            regInfo.setInfoText(SysExecRsUtil.getMsgFromCode(0));
            return JSON.toJSONString(regInfo);
        }
    }

    /**
     * 获取服务器验证码
     *
     * @return
     */
    @RequestMapping("get_sys_code")
    private String getSysCode(HttpServletResponse response, HttpServletRequest request) {
        // 在发送阿里验证码之后即可删除
        int sysCode = (int) ((Math.random() * 9 + 1) * 1000);
        request.getSession().setAttribute("sysCode", sysCode);
        return ajaxReturn(response, sysCode);
    }

    /**
     *
     * @Title: 检查短信验证码
     * @Description: TODO
     * @param response
     * @param request
     * @param userPhone
     * @param smsCode
     * @return
     */
    @RequestMapping("check_code")
    private String checkCode(HttpServletResponse response, HttpServletRequest request,
                             @RequestParam("userPhone") String userPhone, @RequestParam("smsCode") String smsCode) {
        /*Integer currentTime = (Integer) request.getSession().getAttribute("currentTime");
        String checkCode = (String) request.getSession().getAttribute("checkCode");
        String phone = (String) request.getSession().getAttribute("phone");*/
        Sms sms = smsService.findByPhone(userPhone);
        Long currentTime = sms.getCurTime();
        String checkCode = sms.getChkCode();
        String phone = sms.getPhone();
        if (currentTime == null || checkCode == null || phone == null) {
            return ajaxReturn(response, null, "验证码已经超时", -1);
        }

        int overtime = 60 * 5;// 超时时限五分钟;
        if (System.currentTimeMillis() - overtime > currentTime) {
            // 已超时
            request.getSession().removeAttribute("checkCode");
            request.getSession().removeAttribute("phone");
            request.getSession().removeAttribute("currentTime");
            return ajaxReturn(response, null, "验证码已经超时", -1);
        }

            if (phone.equals(userPhone) && checkCode.equals(smsCode)) {
                return ajaxReturn(response, null, "验证成功", 1);
            } else {
            return ajaxReturn(response, null, "验证错误", 0);
        }
    }

    /**
     * 普通用户注册
     *
     *
     */
    @RequestMapping(value = "/reg",method = RequestMethod.POST)
    public String reg(RegEntity entity, HttpServletResponse response, HttpServletRequest request) {
        System.out.println("getContentType:"+request.getContentType()+"\n");
        System.out.println("getCharacterEncoding:"+request.getCharacterEncoding()+"\n");
        System.out.println("getMethod:"+request.getMethod()+"\n");
        System.out.println("entity:"+entity.toString()+"\n");
        System.out.println("phone:"+entity.getPhone()+"\n");
        System.out.println("=====================");
        Enumeration enu=request.getParameterNames();
        while(enu.hasMoreElements()){
            String paraName=(String)enu.nextElement();
            System.out.println(paraName+": "+request.getParameter(paraName));
        }

        Sms sms = smsService.findByPhone(entity.getPhone());
        if (sms == null || entity.getPhone()==null) {
            return ajaxReturn(response, null, "请先获取验证码", -1);
        }

        Long currentTime = sms.getCurTime();
        String checkCode = sms.getChkCode();
        String phone = sms.getPhone();
        if (currentTime == null || checkCode== null) {
            return ajaxReturn(response, null, "验证码已失效", -1);
        }
        int overtime = 60 * 5;// 超时时限五分钟;
        Long a = System.currentTimeMillis();
        /*if (System.currentTimeMillis() - overtime > currentTime) {
            // 已超时
            request.getSession().removeAttribute("checkCode");
            request.getSession().removeAttribute("phone");
            request.getSession().removeAttribute("currentTime");
            return ajaxReturn(response, null, "验证码已经超时", -1);
        }*/

        if (phone.equals(entity.getPhone()) && checkCode.equals(entity.getValidateCode())) {

            User user = new User();
            user.setTelephone(entity.getPhone());
            user.setPwd(bCryptPasswordEncoder.encode(entity.getPassword()));
            user.setLevel(1);
            user.setStatus(1);
            user.setRegTime(new Date());
            user.setJoinTime(new Date());
            Integer userId = 0;
            user.setIntegral(0);
            if(userService.findByTelePhone(entity.getPhone())==null){
                userId = userService.insert(user).getId();
            }else{
                userId = userService.findByTelePhone(phone).getId();
            }

            /*if (userId == 0) {
                request.getSession().removeAttribute("checkCode");
                request.getSession().removeAttribute("phone");
                request.getSession().removeAttribute("currentTime");
                return ajaxReturn(response, null, "注册失败", 0);
            } else {
                request.getSession().removeAttribute("checkCode");
                request.getSession().removeAttribute("phone");
                request.getSession().removeAttribute("currentTime");*/

                user = userService.findById(userId);

                Security securityCfg = (Security) SpringContextUtil.getBean("security");
                Map<String, Object> claims = new HashMap<String, Object>();//创建payload的私有声明
                String[] roles = user.getLevel().toString().split(",");
                Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
                for(String role : roles)
                {
                    authorities.add(new SimpleGrantedAuthority(role));
                }
                claims.put("uid", user.getId());
                claims.put("level",authorities);
                String token = Jwts.builder()
                        .setClaims(claims)//如果有私有声明，一定要先设置这个自己创建的私有的声明，这个是给builder的claim赋值，一旦写在标准的声明赋值之后，就是覆盖了标准的声明
                        //.setId(id)//设置jti(JWT ID)：是JWT的唯一标识，根据业务需要，这个可以设置为一个不重复的值，主要用来作为一次性token,从而回避重放攻击。
                        .setSubject(user.getTelephone())//主体
                        .setExpiration(new Date(System.currentTimeMillis() + 60 * 60 * 24 * 365 * 1000))
                        .signWith(SignatureAlgorithm.HS512, securityCfg.getKey())
                        .compact();
                response.addHeader("Authorization", "Bearer " + token);

                // 默认注册后登录
                //String idAddress = IPUtils.getClientIpAddress(request);// 获取当前ip
                //user.setIp(idAddress);
                //user.setLoginTime(Fn.time());
                //userService.update(user);

                smsService.delSms(phone);

                return ajaxReturn(response, null, "登录成功", 1);
            /*}*/
        } else {
            return ajaxReturn(response, null, "验证错误", 0);
        }

    }


    /**
     *
     * @param entity
     * @param response
     * @param request
     * @return
     */
    @RequestMapping(value = "/npLogin",method = RequestMethod.POST)
    public String npLogin(RegEntity entity, HttpServletResponse response, HttpServletRequest request) {
        System.out.println("phone:"+entity.getPhone()+"\n");
        System.out.println("password:"+entity.getPassword()+"\n");
        Integer userId = 0;
        //判断用户是否存在及用户登录密码是否输入正确
        if (entity.getPassword() != null && entity.getPhone() != null) {
            //获取用户名信息 判断是都存在
            User u = userService.findLoginName(entity.getPhone());
            if (u != null){
                if (bCryptPasswordEncoder.matches(entity.getPassword().toString(),u.getPwd().toString())){
                    System.out.println("密码验证通过================");
                    Security securityCfg = (Security) SpringContextUtil.getBean("security");
                    Map<String, Object> claims = new HashMap<String, Object>();//创建payload的私有声明
                    String[] roles = u.getLevel().toString().split(",");
                    Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
                    for(String role : roles)
                    {
                        authorities.add(new SimpleGrantedAuthority(role));
                    }
                    claims.put("uid", u.getId());
                    claims.put("level",authorities);
                    String token = Jwts.builder()
                            .setClaims(claims)//如果有私有声明，一定要先设置这个自己创建的私有的声明，这个是给builder的claim赋值，一旦写在标准的声明赋值之后，就是覆盖了标准的声明
                            //.setId(id)//设置jti(JWT ID)：是JWT的唯一标识，根据业务需要，这个可以设置为一个不重复的值，主要用来作为一次性token,从而回避重放攻击。
                            .setSubject(u.getTelephone())//主体
                            .setExpiration(new Date(System.currentTimeMillis() + 60 * 60 * 24 * 365 * 1000))
                            .signWith(SignatureAlgorithm.HS512, securityCfg.getKey())
                            .compact();
                    response.addHeader("Authorization", "Bearer " + token);
                    return ajaxReturn(response, null, "登录成功", 1);
                }else{
                    System.out.println("乖乖================》");
                    return ajaxReturn(response, null, "登录失败！", 0);
                }
            }else{
                return ajaxReturn(response, null, "登录失败！", 0);
            }
        } else {
            return ajaxReturn(response, null, "验证错误", 0);
        }
    }

    //门店列表-门店经纪人申请
    @ResponseBody
    @RequestMapping("/shopList")
    public String customerList(ShopEntity entity, HttpServletRequest request) {
        return JSON.toJSONString(shopService.getAll());
    }


    @ResponseBody
    @RequestMapping(value = "/login",method = RequestMethod.POST)
    public String login(RegEntity entity, HttpServletRequest request, HttpServletResponse response){
        System.out.println("I'm In!!!");
        return JSON.toJSONString("successfully");
    }

    @ResponseBody
    @RequestMapping(value = "/login1",method = RequestMethod.POST)
    public String login1(RegEntity entity, HttpServletRequest request, HttpServletResponse response){
        String phone = entity.getPhone();
        String password = entity.getPassword();
        System.out.println(phone+","+password);

        int keycode = Integer.parseInt(entity.getValidateCode());
        Integer sysCode = (Integer) request.getSession().getAttribute("sysCode");
        if (sysCode != keycode) {
            return ajaxReturn(response, null, "请输入正确的验证码", 0);
        }else{
            // 查找用户是否存在
            if (!userService.isExistPhone(phone))
                return ajaxReturn(response, null, "该帐号尚未注册！", -1);

            User user = userService.getUserByProperty(phone, bCryptPasswordEncoder.encode(password));//DigestUtils.md5DigestAsHex(password.getBytes())

            if (user != null) {
                if (user.getStatus() == 0) {
                    return ajaxReturn(response, null, "您的账号已被冻结", 0);
                }else{
                    /*List roleList = new ArrayList<>();
                    String subject = user.getTelephone() + "-" + roleList;
                    String token = Jwts.builder()
                            .setSubject(subject)
                            .setExpiration(new Date(System.currentTimeMillis() + 365 * 24 * 60 * 60 * 1000))
                            .signWith(SignatureAlgorithm.HS512, "MyJwtSecret")
                            .compact();
                    // 登录成功后，返回token到header里面
                    response.addHeader("Authorization", "Bearer " + token);*/
                    System.out.println("111111");
                }
            }else{
                return ajaxReturn(response, null, "你输入的密码和账户名不匹配", -2);
            }

            String projectName = request.getServletContext().getContextPath();

            /*String idAddress = IPUtils.getClientIpAddress(request);// 获取当前ip
            user.setIp(idAddress);
            user.setLoginTime(Fn.time());*/

            //iUserService.update(user);

            return ajaxReturn(response, null, "登录成功", 1);
        }
    }

    @ResponseBody
    @RequestMapping(value = "/agreement/{id}",method = RequestMethod.GET)
    public String agreement(@PathVariable Integer id){
        return JSON.toJSONString(agreementService.getOne(id));
    }

    @ResponseBody
    @RequestMapping(value = "/getCity",method = RequestMethod.GET)
    public String getCity(@RequestParam Integer areaId){
        return JSON.toJSONString(cityService.getPCAIdByAreaId(areaId));
    }

    @ResponseBody
    @RequestMapping(value = "/getHouseList")
    public List<HouseDetail> getHouseList(HouseEntity houseEntity, HttpServletRequest request){
        return houseDetailService.findPagedByWhereClause(houseEntity).getContent();
    }

    /*
     * @Author Danny
     * @Description //进入提供姓名、身份证页面
     * @Date 2019/5/23
     * @Param [entity, request]
     * @Return java.lang.String
     **/
    @ResponseBody
    @RequestMapping("/inviteFace2Face")
    public String inviteFace2Face(UserEntity entity, HttpServletRequest request, HttpServletResponse response){
        int code = -1041;
        User inviteUser = userService.findById(Integer.parseInt(entity.getUpId()));
        String phone = request.getSession().getAttribute("user").toString();
        if(phone!=null && phone.length()==11){//已登录 判断身份 绑定upId
            User currentUser = userService.findByTelePhone(phone);
            if(currentUser!=null){
                if(currentUser.getUpId()!=null && currentUser.getUpId().toString()!=""){//已接受邀请
                    code = -1042;
                }
                if(currentUser.getLevel()==1){//普通用户需完善资料
                    currentUser.setName(entity.getName());
                    currentUser.setPersonalId(entity.getPersonalId());
                    currentUser.setUpId(Integer.parseInt(entity.getUpId()));
                    currentUser.setLevel(2);
                    currentUser.setJoinTime(new Date());
                    User updatedUser = userService.updateUserInfo(currentUser);

                    Security securityCfg = (Security) SpringContextUtil.getBean("security");
                    Map<String, Object> claims = new HashMap<String, Object>();//创建payload的私有声明
                    String[] roles = updatedUser.getLevel().toString().split(",");
                    Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
                    for(String role : roles)
                    {
                        authorities.add(new SimpleGrantedAuthority(role));
                    }
                    claims.put("uid", updatedUser.getId());
                    claims.put("level",authorities);
                    String token = Jwts.builder()
                            .setClaims(claims)//如果有私有声明，一定要先设置这个自己创建的私有的声明，这个是给builder的claim赋值，一旦写在标准的声明赋值之后，就是覆盖了标准的声明
                            //.setId(id)//设置jti(JWT ID)：是JWT的唯一标识，根据业务需要，这个可以设置为一个不重复的值，主要用来作为一次性token,从而回避重放攻击。
                            .setSubject(updatedUser.getTelephone())//主体
                            .setExpiration(new Date(System.currentTimeMillis() + 60 * 60 * 24 * 365 * 1000))
                            .signWith(SignatureAlgorithm.HS512, securityCfg.getKey())
                            .compact();
                    response.addHeader("Authorization", "Bearer " + token);

                    code = 1;
                }
            }
        }else{//未登录 完善资料新增为独立经纪人并绑定upId
            User newUser = new User();
            newUser.setTelephone(entity.getPhone());
            newUser.setPwd(bCryptPasswordEncoder.encode("123456"));
            newUser.setName(entity.getName());
            newUser.setPersonalId(entity.getPersonalId());
            newUser.setUpId(Integer.parseInt(entity.getUpId()));
            newUser.setLevel(2);
            newUser.setStatus(1);
            newUser.setJoinTime(new Date());
            newUser.setRegTime(new Date());
            User updatedUser = userService.updateUserInfo(newUser);

            Security securityCfg = (Security) SpringContextUtil.getBean("security");
            Map<String, Object> claims = new HashMap<String, Object>();//创建payload的私有声明
            String[] roles = updatedUser.getLevel().toString().split(",");
            Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
            for(String role : roles)
            {
                authorities.add(new SimpleGrantedAuthority(role));
            }
            claims.put("uid", updatedUser.getId());
            claims.put("level",authorities);
            String token = Jwts.builder()
                    .setClaims(claims)//如果有私有声明，一定要先设置这个自己创建的私有的声明，这个是给builder的claim赋值，一旦写在标准的声明赋值之后，就是覆盖了标准的声明
                    //.setId(id)//设置jti(JWT ID)：是JWT的唯一标识，根据业务需要，这个可以设置为一个不重复的值，主要用来作为一次性token,从而回避重放攻击。
                    .setSubject(updatedUser.getTelephone())//主体
                    .setExpiration(new Date(System.currentTimeMillis() + 60 * 60 * 24 * 365 * 1000))
                    .signWith(SignatureAlgorithm.HS512, securityCfg.getKey())
                    .compact();
            response.addHeader("Authorization", "Bearer " + token);

            code = 1;
        }
        entity.setInfoCode(code);
        entity.setInfoText(SysExecRsUtil.getMsgFromCode(code));
        return JSON.toJSONString(entity);
    }

    /**
     * 微信回调支付信息
     * @param request
     * @return
    @RequestMapping(value = "/wx/wxNotify")
    @ResponseBody*/


    /**
     * 获取地址信息
     * @param entity
     * @param request
     * @param response
     * @return
     * @throws UnsupportedEncodingException
     */
    @ResponseBody
    @RequestMapping(value = "/getJwd",method = RequestMethod.GET)
    public String getJwd(ApplyEntity entity,HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
        String address = request.getParameter("address");
        String fullStr = new String(address.getBytes("UTF-8"), "UTF-8");
        String url = "https://apis.map.qq.com/ws/geocoder/v1?address="+fullStr+"&key=HZWBZ-KVBKK-CK3J3-A4ZQE-KKCRJ-UBB6B";
        String jsonStr = "";
        return  HttpClientUtil.doGet(url, jsonStr, "utf-8");
    }

}
